#ifndef _NF_SOCS_TYPES_H
#define _NF_SOCS_TYPES_H
#include <linux/types.h>
#ifdef __KERNEL__
#include <linux/in.h>
#include <linux/in6.h>
#else
#include <stdbool.h>
#include <string.h>
#include <arpa/inet.h>
#endif
#include <linux/netfilter.h>
#include <linux/errno.h>

#include "socs/comm/constants.h"


#ifdef __KERNEL__
#define log_error(func, id, text, ...) func("%s: ERR%d (%s): " text "\n", MODULE_NAME, id, \
            __func__, ##__VA_ARGS__)
#define log_informational(func, text, ...) func(text "\n", ##__VA_ARGS__)
#else
#define log_error(func, id, text, ...) printf("ERR%d: " text "\n", id, ##__VA_ARGS__)
#define log_informational(func, text, ...) printf(text "\n", ##__VA_ARGS__)
#endif

#define SOCS_DEBUG

#ifdef SOCS_DEBUG
/** Messages to help us walk through a run. */
#define log_debug(text, ...)    log_informational(pr_debug, text, ##__VA_ARGS__)
#else
#define log_debug(text, ...)
#endif
/** "I'm dropping the packet and it's perfectly normal." */
#define log_info(text, ...)     log_informational(pr_info, text, ##__VA_ARGS__)
/** "I'm dropping the packet because it's corrupted." (i. e. nothing's wrong with the NAT64) */
#define log_warning(text, ...)  log_informational(pr_warning, text, ##__VA_ARGS__)
/** "I'm dropping the packet because the config's flipped out or a kmalloc failed." */
#define log_err(id, text, ...)  log_error(pr_err, id, text, ##__VA_ARGS__)
/** "I'm dropping the packet because I detected a programming error." */
#define log_crit(id, text, ...) log_error(pr_crit, id, text, ##__VA_ARGS__)


enum error_code {
	/*transmit*/

	ERR_TRANS_FAILED = 2000,

	ERR_ALLOC_FAILED = 3000,
	ERR_ADD_FAILED   = 3001,
	ERR_REMOVE_FAILED = 3002,

	ERR_UNKNOW_OPT = 4000,
	ERR_UNKNOW_KEY = 4001,
	ERR_UNKNOW_FAMILY = 4002,

	ERR_MULSEND_FAILED = 5000,
	ERR_NLSEND_FAILED = 5001,

	ERR_NULL_PTR = 6000,
	ERR_TIMER = 7000,
	ERR_PID = 8000,
	ERR_SOCKET = 9000
};

enum hello_opt_type {
	HELLO_BASIC = 0, /*kernel send localnode info to usr and usr send to neigh*/
	HELLO_VOTE = 1,
	HELLO_EXPIRE = 2,
	HELLO_GRAB = 3,
	HELLO_OK = 4,
	HELLO = 5,
	HELLO_PRE = 6
};
enum saIP_status {
	NODIP = 0,
	GRABBING = 1,
	ABANDONING = 2,
	SERVING = 3
};
enum hello_vote_type {
	NOVOTE = 0,
	MAP = 1,
	SAP = 2,
	PRE = 3 //chenjq

};
enum vote_result {
	VOTE_SUCCESS = 0,
	VOTE_CONTINUE = 1,
	VOTE_FINISH = 2,
	VOTE_FAILED = 3
};
enum trans_result {
	TRANS_SUCCESS = 0,
	TRANS_LOCAL = 1,
	TRANS_FAILED = 2
};
enum family_type {
	FAMILY_INVALID = -1,
	IPV4 = 0,
	IPV6 = 1,
	FAMILY_NUM,
};

#define FAMILY_IS_VALID(family) ((family) > FAMILY_INVALID && (family) < FAMILY_NUM)

struct hello_packet {
	int opt;
	int vote_type;
	char csDomain[CSSIZE];
	int data_len;
	char data[0];
};
/***********************talk to user*******************************/
struct ipv6_prefix {
	/** IPv6 prefix. */
	struct in6_addr address;
	/** Number of bits from "address" which represent the network. */
	__u8 len;
};

struct arguments {
	__u16 key;
	__u32 operation;

	struct in_addr saIP4;
	struct in6_addr  saIP6;

	char csDomain[CSSIZE];
	char hostname[HOSTNAMESIZE];
	unsigned int tmHello;
	unsigned int tmDead;
	unsigned int tmStable;
	struct in6_addr mcIP6;
	struct in_addr mcIP4;

	struct ipv6_prefix prefix6;
};

enum argp_flags {
	/*key*/
	ARGP_POOL6 = '6',
	ARGP_SHOW = 's',
	ARGP_CSDOMAIN = 'c',
	ARGP_HOSTNAME = 'n',

	ARGP_TMHELLO = 1000,
	ARGP_TMDEAD = 1001,
	ARGP_TMSTABLE = 1002,

	ARGP_MCIP4 = 1003,
	ARGP_MCIP6 = 1004,

	ARGP_SAIP  = 2000,
	ARGP_SAIP4 = 2001,/*only have -- do not have -*/
	ARGP_SAIP6 = 2002,/*only have -- do not have -*/
	ARGP_NEIGH = 2003,
	ARGP_PREFIX6 = 2004,
	ARGP_PREFIX6_ALL = 2005,

	/* Pools */
	ARGP_PREFIX = 2010,

	/*operation*/
	ARGP_DISPLAY = 'd',
	ARGP_ADD = 'a',
	ARGP_REMOVE = 'r',
	ARGP_FLUSH = 'f',
};

#endif
